package cn.lzm.system.service.impl;

import cn.lzm.basic.anno.PreAuthorize;
import cn.lzm.system.domain.Permission;
import cn.lzm.system.mapper.PermissionMapper;
import cn.lzm.system.service.IPermissionService;
import cn.lzm.basic.service.impl.BaseServiceImpl;
import cn.lzm.basic.util.Classutil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.*;

import java.io.File;
import java.io.FileFilter;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author lzm
 * @since 2022-10-24
 */
@Service
public class PermissionServiceImpl extends BaseServiceImpl<Permission> implements IPermissionService {
    // 扫描路径包前缀
    private static final String PKG_PREFIX = "cn.lzm.";
    // 扫描路径包后缀
    private static final String PKG_SUFFIX = ".controller";

    @Autowired
    private PermissionMapper permissionMapper;

    @Override
    public void scanPermission() {
        // 1.获取cn.lzm下面所有的模块目录
        String path= this.getClass().getResource("/").getPath()+"/cn/lzm";
        File file = new File(path);
        File[] files = file.listFiles(new FileFilter() {
            @Override
            public boolean accept(File pathname) {
                return file.isDirectory();
            }
        });

        // 获取cn.lzm.*.controller里面所有的类
        HashSet<Class> clazzes = new HashSet<>();
        for (File fileTmp : files) {
            clazzes.addAll(Classutil.getClasses(PKG_PREFIX+fileTmp.getName()+PKG_SUFFIX));

        }

        // 遍历所有类
        for (Class clazz : clazzes) {
            // 获取所有方法，若没有方法 就结束本次循环
            Method[] methods = clazz.getMethods();
            if (methods==null || methods.length<1){
                continue;
            }
            // 类中有方法
            for (Method method : methods) {
                // 得到该方法的请求地址
                String uri = getUri(clazz, method);
                // 获取类上的自定义注解，判断如果没有结束循环
                PreAuthorize annotation = method.getAnnotation(PreAuthorize.class);
                if (annotation == null) {
                    continue;
                }
                String name = annotation.name();
                String sn = annotation.sn();

                Permission permission = permissionMapper.findBySn(sn);
                // 5.如果不存在就添加权限
                if (permission == null) {
                    Permission permission1 = new Permission();
                    permission1.setName(name);
                    permission1.setSn(sn);
                    permission1.setUrl(uri);
                    permissionMapper.add(permission1);
                } else { // 6.如果存在就修改权限
                    permission.setName(name);
                    permission.setSn(sn);
                    permission.setUrl(uri);
                    permissionMapper.update(permission);
                }
            }
        }
    }
    /**
     * 根据类的字节码和类的方法得到方法的请求地址
     */
    /**
     * @Description: 根据类的字节码和类的方法得到方法的请求地址
     * @Author: July
     * @Date: 2022/7/10 23:37
     * @param clazz: 类字节码对象
     * @param method: 方法对象
     * @return: java.lang.String
     **/
    private String getUri(Class clazz, Method method) {
        String classPath = "";
        Annotation annotation = clazz.getAnnotation(RequestMapping.class);
        if (annotation != null) {
            RequestMapping requestMapping = (RequestMapping) annotation;
            String[] values = requestMapping.value();
            if (values != null && values.length > 0) {
                classPath = values[0];
                if (!"".equals(classPath) && !classPath.startsWith("/"))
                    classPath = "/" + classPath;
            }
        }
        GetMapping getMapping = method.getAnnotation(GetMapping.class);
        String methodPath = "";
        if (getMapping != null) {
            String[] values = getMapping.value();
            if (values != null && values.length > 0) {
                methodPath = values[0];
                if (!"".equals(methodPath) && !methodPath.startsWith("/"))
                    methodPath = "/" + methodPath;
            }
        }
        PostMapping postMapping = method.getAnnotation(PostMapping.class);
        if (postMapping != null) {
            String[] values = postMapping.value();
            if (values != null && values.length > 0) {
                methodPath = values[0];
                if (!"".equals(methodPath) && !methodPath.startsWith("/"))
                    methodPath = "/" + methodPath;
            }
        }
        DeleteMapping deleteMapping = method.getAnnotation(DeleteMapping.class);
        if (deleteMapping != null) {
            String[] values = deleteMapping.value();
            if (values != null && values.length > 0) {
                methodPath = values[0];
                if (!"".equals(methodPath) && !methodPath.startsWith("/"))
                    methodPath = "/" + methodPath;
            }
        }
        PutMapping putMapping = method.getAnnotation(PutMapping.class);
        if (putMapping != null) {
            String[] values = putMapping.value();
            if (values != null && values.length > 0) {
                methodPath = values[0];
                if (!"".equals(methodPath) && !methodPath.startsWith("/"))
                    methodPath = "/" + methodPath;
            }

        }
        PatchMapping patchMapping = method.getAnnotation(PatchMapping.class);
        if (patchMapping != null) {
            String[] values = patchMapping.value();
            if (values != null && values.length > 0) {
                methodPath = values[0];
                if (!"".equals(methodPath) && !methodPath.startsWith("/"))
                    methodPath = "/" + methodPath;
            }
        }
        RequestMapping requestMapping = method.getAnnotation(RequestMapping.class);
        if (requestMapping != null) {
            String[] values = requestMapping.value();
            if (values != null && values.length > 0) {
                methodPath = values[0];
                if (!"".equals(methodPath) && !methodPath.startsWith("/"))
                    methodPath = "/" + methodPath;
            }
        }
        return classPath + methodPath;
    }

    private String getPermissionSn(String value) {
        String regex = "\\[(.*?)]";
        Pattern p = Pattern.compile("(?<=\\()[^\\)]+");
        Matcher m = p.matcher(value);
        String permissionSn = null;
        if (m.find()) {
            permissionSn = m.group(0).substring(1, m.group().length() - 1);
        }
        return permissionSn;
    }
}
